'''m3u8下载线程.

线程参数data={'m3u8':下载的m3u8链接,'target':下载目标文件}
状态表self._status['status']={'msg': 以字符串格式显示的状态信息}
'''

import re
import time

import requests
from requests.adapters import HTTPAdapter

from BaseThread import BaseThread

class m3u8Thread(BaseThread):

  def __init__(self):
    BaseThread.__init__(self)
    self._m3u8 = None
    self._target = None
    self._links = None # 下载的链接表
    self._session = requests.Session()
    self._session.mount('http://', HTTPAdapter(max_retries=3))
    self._session.mount('https://', HTTPAdapter(max_retries=3))
    return

  def _thread(self, data):
    self._status['status']['msg'] = 'm3u8下载线程开始!'
    self._m3u8 = data['m3u8']
    self._target = data['target']
    print(f'm3u8Thread 开始运行, m3u8 = {self._m3u8},target = {self._target}')
    self._status['status']['msg'] = '正在分析m3u8链接获取下载内容'
    self._links = self._handleM3u8(self._m3u8)
    self._download(self._links, self._target)
    return '下载完成!'
    
  ## 分析m3u8,生成下载列表并返回该列表,分析失败则返回空列表
  def _handleM3u8(self, m3u8):
    result = []
    urlTop = re.sub(r'[^/]*$', '', m3u8)
    resp = self._session.get(m3u8)
    texts = filter(lambda x:(not (x.startswith('#'))) and 
      (len(x.strip()) > 0), resp.text.split('\n'))
    for url in texts:
      if url.endswith('.m3u8'):
        result += self._handleM3u8(urlTop+url)
      else:
        result.append(urlTop+url)
    return result
  
  ## 下载指定的链接表,并合并成target指定路径的文件,可指定缓存大小(默认20MB)
  def _download(self, links, target, bufferSize = 1024*1024*20):
    tempContent = b'' # 下载的内容的总和,每到缓存前清空一次
    totalParts = len(links) # 下载部分数
    for i in range(0, totalParts):
      self._status['status']['msg'] = f'下载进度: {i}/{totalParts}'
      link = links[i]
      resp = self._session.get(link)
      if resp.status_code != 200:
        raise Exception(f'resp.status_code != {resp.status_code}')
        return
      tempContent += resp.content
      ## 缓存大小够了就写入文件
      if len(tempContent) > bufferSize:
        with open(target, 'ab+') as f:
          f.write(tempContent)
        tempContent = b''
    ## 完成,把最后部分写入文件
    with open(target, 'ab+') as f:
      f.write(tempContent)
    return
